﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Common
{
    /// <summary>
    /// 批量注入业务服务接口
    /// </summary>
    public interface IBllDependency
    {
    }

    /// <summary>
    /// 简单Ioc帮助类（依赖容器注入）
    /// https://blog.csdn.net/weixin_48083386/article/details/121348476
    /// </summary>
    public class SimpleIocHelper
    {
        /// <summary>
        /// 容器字典
        /// </summary>
        private static Dictionary<Type, Type> ContainerDictionary { get; set; }

        static SimpleIocHelper()
        {
            InitContainerDic();
        }

        /// <summary>
        /// 注册
        /// </summary>
        /// <typeparam name="TServiceType"></typeparam>
        /// <typeparam name="TImplementType"></typeparam>
        public static void Register<TServiceType, TImplementType>()
        {
            try
            {
                ContainerDictionary.Add(typeof(TServiceType), typeof(TImplementType));
            }
            //重复添加Key的异常处理
            catch (ArgumentException ex)
            {

            }
        }

        /// <summary>
        /// 注入
        /// </summary>
        /// <typeparam name="TServiceType"></typeparam>
        /// <returns></returns>
        public static TServiceType Resolve<TServiceType>()
        {
            TServiceType result = default(TServiceType);

            Type implementType = ContainerDictionary[typeof(TServiceType)];
            result = (TServiceType)CreateObject(implementType);

            return result;
        }

        #region 私有方法
        /// <summary>
        /// 初始化容器字典
        /// </summary>
        /// <returns></returns>
        private static void InitContainerDic()
        {
            ContainerDictionary = new Dictionary<Type, Type>();
            //排除注册的接口类型
            Type[] exceptType = new Type[] { typeof(IBllDependency), typeof(IDisposable) };

            foreach (var assembly in AssemblyUtility.AllReferencedAssemblies)
            {
                //所有符合注册条件的类集合
                try
                {
                    Type[] targetTypes = assembly.GetTypes().Where(a => !a.IsAbstract && !a.IsInterface && !a.IsSealed && typeof(IBllDependency).IsAssignableFrom(a)).ToArray();
                    foreach (var targetType in targetTypes)
                    {
                        //获取符合注册条件的类的接口（除了baseType）
                        foreach (var interfaceType in targetType.GetInterfaces().Except(exceptType))
                        {
                            ContainerDictionary.Add(interfaceType, targetType);
                        }
                    }
                }
                //重复添加Key的异常处理
                catch (ArgumentException ex)
                {
                }
                catch (Exception ex)
                {
                }
            }
        }

        /// <summary>
        /// 创建对象
        /// Tip：依据构造函数递归创建
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private static object CreateObject(Type type)
        {
            //获取构造函数
            ConstructorInfo[] cons = type.GetConstructors();

            List<object> paraList = new List<object>();

            //如果构造函数数量大于0
            if (cons.Count() > 0)
            {
                //选择参数数量最多的构造函数
                ConstructorInfo con = cons.OrderByDescending(c => c.GetParameters().Length).FirstOrDefault();
                foreach (ParameterInfo para in con.GetParameters())
                {
                    Type paraType = para.ParameterType;
                    //字典容器查询出具体的参数对象类型
                    Type targetType = ContainerDictionary[paraType];
                    //递归实例化所有参数对象，以及其依赖的对象，并添加到数组中
                    paraList.Add(CreateObject(targetType));
                }
            }

            //返回对象
            return Activator.CreateInstance(type, paraList.ToArray());
        }
        #endregion
    }
}
